package team2.game.crow;

import java.util.ArrayList;
import java.util.List;

import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.handler.timer.ITimerCallback;
import org.anddev.andengine.engine.handler.timer.TimerHandler;
import org.anddev.andengine.entity.text.Text;
import org.anddev.andengine.util.Debug;
import org.andengine.bulletml.simple.BossData;
import org.andengine.shmup.Boss;
import org.andengine.shmup.Enemy;
import org.andengine.shmup.EnemyWave;
import org.andengine.shmup.GameContainer;
import org.andengine.shmup.Level;

public class LevelHandler implements IUpdateHandler {

	// ===========================================================
	// Constants
	// ===========================================================

	// ===========================================================
	// Fields
	// ===========================================================
	
	private GameContainer game;
	private CrowActivity main;
	private List<Level> levels;
	private Level currentLevel;
	private int levelNumber;
	private Boss currentBoss;
	private ArrayList<Boss> bosses;
	private int waveTime;
	private int enteringLevel;
	private int exitingLevel;
	private float timeElapsed;
	private float exitTimeElapsed;
	private boolean bossSpawned;
	private boolean runLevel;
	private boolean notEntered;
	private boolean notReady;
	private LevelBackground currentBackground;
	
	// ===========================================================
	// Constructors
	// ===========================================================
	
	public LevelHandler(final GameContainer gc,final CrowActivity main, final ArrayList<Boss> bosses){
		this.game = gc;
		this.main = main;
		this.bosses = bosses;
		this.waveTime = 5;
		this.enteringLevel = 17;
		this.exitingLevel = 10;
		this.timeElapsed = 0;
		this.levelNumber = 0;
		this.exitTimeElapsed = 0;
		this.bossSpawned = false;
		this.runLevel = false;
		this.notEntered = true;
		this.notReady = true;
		this.currentBackground = new LevelBackground(main.backgroundOne1,main.backgroundOne2,main.backgroundOne3,main.backgroundOne4,main);
		main.scene.registerUpdateHandler(currentBackground);
		
		levels = game.getLevels();
		currentLevel = levels.get(levelNumber);
	}
	
	// ===========================================================
	// Getter & Setter
	// ===========================================================

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================
	
	@Override
	public void onUpdate(float delta) {
		timeElapsed += delta;
		
		if(timeElapsed > enteringLevel){
			runLevel = true;
		}
		else{
			if(timeElapsed > 4 && notEntered){
				if(main.blankScreen.hasParent()){
					main.scene.detachChild(main.blankScreen);
				}
				displayText("Entering Level: "+(levelNumber+1),5);
				spawnBackground();
				notEntered = false;
			}
			if(timeElapsed > 12 && notReady){
				displayText("GET READY!!", 5);
				notReady = false;
			}
		}
		
		if(runLevel && timeElapsed > waveTime){
			timeElapsed = 0;
			Debug.d("Enemies Spawned...");
			if(spawnEnemies() != true){
				if(!bossSpawned){
					spawnBoss(levelNumber);
					bossSpawned = true;
					currentBackground.setScrolling(false);
				}				
			}
			
		}
		
		if(main.levelDone){//Need a giant Explosion for transition
			exitTimeElapsed += delta;
			main.crow.dramaticMovement(240, -200);
			if(exitTimeElapsed > exitingLevel){
				main.crow.dramaticMovement(240, 500);
				main.crow.endDrama();
				//main.scene.attachChild(main.blankScreen);//Need to figure how to fade in
				timeElapsed = 0;
				exitTimeElapsed = 0;
				levelNumber++;
				currentLevel = levels.get(levelNumber);
				bossSpawned = false;
				main.levelDone = false;
				runLevel = false;
				notEntered = true;
				notReady = true;
				currentBackground.setScrolling(true);
			}
		}
		
	}

	@Override
	public void reset() {
		// TODO Auto-generated method stub
		
	}
	
	// ===========================================================
	// Methods
	// ===========================================================
	
	private boolean spawnEnemies(){
		if(currentLevel.hasNextWave()){//Spawning enemies
			EnemyWave wave = currentLevel.getNextWave();
			String type = wave.getEnemyType();
			if(type.compareTo("GRUNT") == 0){
				Enemy[] stuff = wave.spawnEnemies(main.gruntPool);
				for(int x = 0; x < stuff.length; x++){
					if(!(stuff[x] == null)){
						main.enemies.add(stuff[x]);
						if(stuff[x].getParent() == null){
							stuff[x].animate(100);
							main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(stuff[x]);
							stuff[x].setBulletPool(main.enemyLaserPool);
							stuff[x].setBulletArray(main.enemyShots);
						}
					}
				}
			}
			else if(type.compareTo("BLADER") == 0){
				Enemy[] stuff = wave.spawnEnemies(main.bladerPool);
				for(int x = 0; x < stuff.length; x++){
					if(!(stuff[x] == null)){
						main.enemies.add(stuff[x]);
						if(stuff[x].getParent() == null){
							stuff[x].animate(100);
							main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(stuff[x]);
							stuff[x].setBulletPool(main.enemyLaserPool);
							stuff[x].setBulletArray(main.enemyShots);
						}
					}
				}
			}
			return true;
		}//End Spawning
		return false;
	}
	
	private void spawnBoss(int bossNumber){	
		BossData data = currentLevel.getBoss();
		switch (bossNumber){
		case 0:
			currentBoss = new Boss(0, 0-main.mFirstBoss.getHeight(), main.mFirstBoss, data, main.superLaser);
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
			main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
			main.bossWeakPoint = currentBoss;
			break;
		case 1:
			currentBoss = new Boss(0, 0-main.mSecondBoss.getHeight(), main.mSecondBoss, data, main.superLaser);
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
			main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
			currentBoss.addExternalAnimSprite(204, 204, main.mSecondBossCore, 80, "core");
			main.bossWeakPoint = currentBoss.addComps.get(0);
			break;
		case 2:
			currentBoss = new Boss(CrowActivity.CAMERA_WIDTH/2 - main.mThirdBoss.getTileWidth()/2,0-main.mThirdBoss.getHeight(), main.mThirdBoss, data, main.superLaser);
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
			main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
			currentBoss.addExternalAnimSprite(currentBoss.getX() + 101, 86, main.mThirdBossCore, 80, "core");
			main.bossWeakPoint = currentBoss.addComps.get(0);
			break;
		case 3:
			//displayText("END GAME GOES HERE \n Press Back to return to main menu.", 5);
			currentBoss = new Boss(CrowActivity.CAMERA_WIDTH/2 - main.mFourthBoss.getTileWidth()/2,0-main.mFourthBoss.getHeight(), main.mFourthBoss, data, main.superLaser);
			currentBoss.animate(100);
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
			main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
			currentBoss.addExternalAnimSprite(currentBoss.getX() + 101, 86, main.mFourthBossCore, 80, "core");
			main.bossWeakPoint = currentBoss.addComps.get(0);
			break;
		case 4:
			currentBoss = new Boss(0,60-main.mFifthBoss.getHeight(), main.mFifthBoss, data, main.superLaser);
            currentBoss.setBulletPool(main.enemyLaserPool);
            currentBoss.setBulletArray(main.enemyShots);
            main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
            currentBoss.init();
            currentBoss.addExternalAnimSprite(393, 13, main.mFifthBossCore, 80, "core");
            main.bossWeakPoint = currentBoss.addComps.get(0);
			break;
		case 5:
			currentBoss = new Boss(CrowActivity.CAMERA_WIDTH/6,0-main.mSixthBoss.getHeight(), main.mSixthBoss, data, main.superLaser);
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
			main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
			currentBoss.addExternalAnimSprite(currentBoss.getX() + currentBoss.getTextureRegion().getTileWidth()/3 + 10, currentBoss.getTextureRegion().getTileHeight()/3 + 10, main.mSixthBossCore, 80, "core");
			main.bossWeakPoint = currentBoss.addComps.get(0);
            break;
		case 6:
			currentBoss = new Boss(0,0-main.mSeventhBoss.getHeight(), main.mSeventhBoss, data, main.superLaser);
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
            main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
            currentBoss.addExternalAnimSprite(195,63, main.mSeventhBossCore, 80, "core");
            main.bossWeakPoint = currentBoss.addComps.get(0);
			break;
		case 7:
			currentBoss = new Boss(0,0-main.mEigthBoss.getHeight(), main.mEigthBoss, data, main.superLaser);
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
            main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
            currentBoss.addExternalAnimSprite(185.5f,230.5f, main.mEigthBossCore, 80, "core");
            main.bossWeakPoint = currentBoss.addComps.get(0);
            break;
		case 8:
			currentBoss = new Boss(0,0, main.mNinthBoss, data, main.superLaser);
			//-main.mNinthBoss.getHeight()
			currentBoss.setBulletPool(main.enemyLaserPool);
			currentBoss.setBulletArray(main.enemyShots);
            main.scene.getChild(CrowActivity.LAYER_FOREGROUND).attachChild(currentBoss);
            main.bossWeakPoint = currentBoss;
            break;
		case 9:
			main.gameOver();
			//currentBoss = new FinalBoss(CrowActivity.CAMERA_WIDTH/2, 0-main.mTenthBoss.getHeight(), main.mTenthBoss, data, main.superLaser);
			break;
		default:
			main.gameOver();
			break;
		}
		//currentBoss.init();
		main.currentBoss = currentBoss;
		Debug.d("Current Boss:"+currentBoss);
	}
	
	public void setLevel(int level){
		this.levelNumber = level;
	}
	
	private void spawnBackground(){
		switch(levelNumber){
		case 0:
			//Do nothing already in the first one there
			break;
		case 1:
			currentBackground.changeBackground(main.backgroundTwo1, main.backgroundTwo2, main.backgroundTwo3, main.backgroundTwo4);
			break;
		case 2:
			currentBackground.changeBackground(main.backgroundThree1, main.backgroundThree2, main.backgroundThree3, main.backgroundThree4);
			break;
		case 3:
			currentBackground.changeBackground(main.backgroundFour1, main.backgroundFour2, main.backgroundFour3, main.backgroundFour4);
			break;
		case 4:
			currentBackground.changeBackground(main.backgroundFive1, main.backgroundFive2, main.backgroundFive3, main.backgroundFive4);
			break;
		case 5:
			currentBackground.changeBackground(main.backgroundSix1, main.backgroundSix2);
			break;
		case 6:
			currentBackground.changeBackground(main.backgroundSeven1, main.backgroundSeven2);
			break;
		case 7:
			currentBackground.changeBackground(main.backgroundEight1, main.backgroundEight2);
			break;
		case 8:
			currentBackground.changeBackground(main.backgroundNine1, main.backgroundNine2);
			break;
		case 9:
			currentBackground.changeBackground(main.backgroundTen1, main.backgroundTen2);
			break;
		}
	}
	
	private void displayText(String text, int duration){
		final Text outstring = new Text(100,600,main.font, text);
		main.scene.getChild(CrowActivity.LAYER_UI).attachChild(outstring);
		main.scene.registerUpdateHandler(new TimerHandler(duration, true, new ITimerCallback(){
			@Override
			public void onTimePassed(final TimerHandler pTimerHandler) {
				main.runOnUpdateThread(new Runnable() {
		            @Override
		            public void run() {
		            	main.scene.getChild(CrowActivity.LAYER_UI).detachChild(outstring);
		            }
				});
			}
		}));
	}
	
	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================
}

